package cl.ccs.migracionbcmc.dao.impl;


import cl.ccs.migracionbcmc.connection.ConnectionFactory;
import cl.ccs.migracionbcmc.dao.CertificadoDao;
import cl.ccs.migracionbcmc.model.Certificado;
import cl.ccs.migracionbcmc.model.CertificadoEmitido;
import cl.ccs.migracionbcmc.model.DatosPersona;
import cl.ccs.migracionbcmc.model.PersonaCertificado;
import cl.ccs.migracionbcmc.model.PersonaCertificadoEmitido;
import cl.ccs.migracionbcmc.model.VerificaCertificado;
import cl.ccs.migracionbcmc.util.Constantes;
import cl.ccs.migracionbcmc.util.Util;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Types;

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class CertificadoDaoImpl implements CertificadoDao{
    
    public CertificadoDaoImpl() {
        super();
    }

    /**
     * @param rut
     * @param cCosto
     * @param login
     * @return
     * @throws Exception
     */
    @Override
    public PersonaCertificado consultaCertificado(String rut,Integer cCosto, String login) throws Exception {
        
        PersonaCertificado persona = new PersonaCertificado();
        
        if(rut == null) {
            return persona;
        }
        
        try {
            rut = Util.formatRUT(rut).toUpperCase();
            
            persona.setDatos(consultaPersona(rut));           
            
            persona.setListCertificado(getListCertificado(rut, persona.getDatos().getCorrNombre(), Constantes.RUT_CCS, cCosto, login));
            
        } catch (Exception e) {
            e.printStackTrace();
        } 

        return persona;
    }

    /**
     * @param rutAfectado
     * @param corrNombre
     * @param rutSolicitante
     * @param cCosto
     * @param login
     * @return
     * @throws Exception
     */
    @Override
    public PersonaCertificado consultaCertificadoPDF(String rutAfectado, Long corrNombre, String rutSolicitante, Integer cCosto,
                                              String login) throws Exception{
        List<Certificado> listCertificado = new ArrayList<Certificado>();
        PersonaCertificado persona = new PersonaCertificado();

        
        Connection con = null;
        ResultSet rs = null;
        if(rutAfectado == null ) {
            return persona;
        }
        
        try {
            
            //en primera instancia, rutAfectado debe ser igual a rutSolicitante
            rutAfectado = Util.formatRUT(rutAfectado);
            rutSolicitante = rutAfectado;

            con = ConnectionFactory.getConnectionSybaseBIC();
            CallableStatement stm = con.prepareCall("{?=CALL SI_TransConsLey20575_ADF(?,?,?,?,?,?,?,?,?)}");
            stm.registerOutParameter(1, Types.INTEGER);
            
            stm.setString(2, rutAfectado);
            stm.setLong(3, corrNombre);
            stm.setString(4, rutSolicitante);
            stm.setInt(5, cCosto);
            stm.setString(6, login);
            stm.setString(7, Constantes.CODIGO_SERVICIO);
            
            stm.registerOutParameter(8, Types.NUMERIC); //Fld_CorrConsulta (Convertir Hexadecimal)
            stm.registerOutParameter(9, Types.DATE);    //Fld_Fecha
            stm.registerOutParameter(10, Types.VARCHAR); //Fld_Mensaje
                 
            
            rs = stm.executeQuery();
            SimpleDateFormat fmtHour = new SimpleDateFormat("HH:mm");
            while (rs.next()) {
                Certificado certificado = new Certificado();
                certificado.setFechaConsulta(rs.getTimestamp("Fld_Fecha"));
                certificado.setHoraConsulta(fmtHour.format(certificado.getFechaConsulta()));
                certificado.setRutRequirente(rs.getString("Fld_RutRequirente"));

                String nombre = rs.getString("Fld_Nombre_Nombres").trim();
                String apPaterno = rs.getString("Fld_Nombre_ApPat").trim();
                String apMaterno = rs.getString("Fld_Nombre_ApMat").trim();

                if (Util.isRutJuridico(certificado.getRutRequirente())) {
                    certificado.setNombreRequirente(apPaterno + apMaterno + nombre);
                } else {
                    certificado.setNombreRequirente(apPaterno + " " + apMaterno + " " + nombre);
                }

                certificado.setMotivo(rs.getString("Fld_CodNemotecnico"));
                certificado.setResponsable(rs.getString("Fld_GlosaResponsable"));
                
                listCertificado.add(certificado);
            }
            
            Long corrConsulta = new Long(stm.getLong(8));
            String codigoVerificacion = Long.toHexString(corrConsulta);
            
            persona.setProximoInforme(stm.getDate(9));
            persona.setCodigoVerificacion(codigoVerificacion.toUpperCase()); 
            persona.setDatos(consultaPersona(rutAfectado));
            persona.setListCertificado(listCertificado);            
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ConnectionFactory.freeConnection(con, rs);
        }
        return persona;
    }

    /**
     * @param rutAfectado
     * @param corrNombre
     * @param rutSolicitante
     * @param cCosto
     * @param login
     * @return
     * @throws Exception
     */
    @Override
    public PersonaCertificado validaCertificadoPDF(String codigo) throws Exception{
        List<Certificado> listCertificado = new ArrayList<Certificado>();
        PersonaCertificado persona = new PersonaCertificado();

        
        Connection con = null;
        ResultSet rs = null;
        if(codigo == null ) {
            return persona;
        }
        
        try {
            
            //en primera instancia, rutAfectado debe ser igual a rutSolicitante
            

            con = ConnectionFactory.getConnectionConsulta();
            CallableStatement stm = con.prepareCall("{?=CALL SQ_ValidaCertifREAD_ADF(?,?,?,?,?,?,?,?,?,?,?)}");

            stm.registerOutParameter(1, Types.INTEGER);
            stm.setString(2, codigo);
            stm.registerOutParameter(3, Types.VARCHAR); //Rut Afectado
            stm.registerOutParameter(4, Types.NUMERIC); //Fld_CodCCosto
            stm.registerOutParameter(5, Types.VARCHAR); //GlosaCCosto
            stm.registerOutParameter(6, Types.VARCHAR); //Fld_Nombre_ApPat
            stm.registerOutParameter(7, Types.VARCHAR); //Fld_Nombre_ApMat
            stm.registerOutParameter(8, Types.VARCHAR); //Fld_Nombre_Nombres
            stm.registerOutParameter(9, Types.DATE); //Fecha solicitud.
            stm.registerOutParameter(10, Types.DATE); //Fecha proximo certificado
            stm.registerOutParameter(11, Types.VARCHAR); //Usuario
            stm.registerOutParameter(12, Types.VARCHAR); //Mensaje
            
            try {
                rs = stm.executeQuery();
            }catch(Exception e) {
                stm.execute();
            }
            
            SimpleDateFormat fmtHour = new SimpleDateFormat("HH:mm");
            while (rs != null && rs.next()) {
                Certificado certificado = new Certificado();
                certificado.setFechaConsulta(rs.getTimestamp("Fld_Fecha"));
                certificado.setHoraConsulta(fmtHour.format(certificado.getFechaConsulta()));
                certificado.setRutRequirente(rs.getString("Fld_RutRequirente"));

                String nombre = rs.getString("Fld_Nombre_Nombres").trim();
                String apPaterno = rs.getString("Fld_Nombre_ApPat").trim();
                String apMaterno = rs.getString("Fld_Nombre_ApMat").trim();

                if (Util.isRutJuridico(certificado.getRutRequirente())) {
                    certificado.setNombreRequirente(apPaterno + apMaterno + nombre);
                } else {
                    certificado.setNombreRequirente(apPaterno + " " + apMaterno + " " + nombre);
                }

                certificado.setMotivo(rs.getString("Fld_CodNemotecnico"));
                //certificado.setResponsable(rs.getString("Fld_GlosaResponsable"));
                
                listCertificado.add(certificado);
            }
            
            if(stm.getInt(1) == 0) {
                throw new Exception(stm.getString(12));
            }
            
            String rutAfectado = stm.getString(3);
            persona.setProximoInforme(stm.getDate(10));
            persona.setFechaConsulta(stm.getDate(9));
            persona.setCodigoVerificacion(codigo.toUpperCase()); 
            persona.setDatos(consultaPersona(rutAfectado));
            persona.setGlosaCCosto(stm.getString(5));
            persona.setUser(stm.getString(11));
            persona.setRutAfectado(rutAfectado);            
            persona.setListCertificado(listCertificado);      
            
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            ConnectionFactory.freeConnection(con, rs);
        }
        return persona;
    }


    /**
     * @param rut
     * @return
     * @throws Exception
     */
    @Override
    public DatosPersona consultaPersona(String rut) throws Exception{
        Connection con = null;
        DatosPersona datos = new DatosPersona();
        if(rut == null) {
            return datos;
        }
        try{
            rut = Util.formatRUT(rut).toUpperCase();
            con = ConnectionFactory.getConnectionSybaseBIC();
            
            
            CallableStatement stm = con.prepareCall("{?=CALL SQ_Nombre_ADF(?, ?, ?, ?, ?, ?)}");
            stm.registerOutParameter(1, Types.INTEGER);
            
            stm.setString(2, rut);
            
            stm.registerOutParameter(3, Types.VARCHAR); //Fld_Nombre_ApPat
            stm.registerOutParameter(4, Types.VARCHAR); //Fld_Nombre_ApMat
            stm.registerOutParameter(5, Types.VARCHAR); //Fld_Nombre_Nombres
            stm.registerOutParameter(6, Types.NUMERIC); //Fld_CorrNombre
            stm.registerOutParameter(7, Types.INTEGER); //Fld_RowCount
            
            stm.execute();
            
            if(stm.getInt(7) == 0) {
                datos.setExists(false);
                return datos; 
            }
            datos.setExists(true);
                    
            
            datos.setApPaterno(stm.getString(3)); 
            datos.setApMaterno(stm.getString(4));
            datos.setNombre(stm.getString(5));
            
            if(Util.isRutJuridico(rut)) {
                datos.setNombreCompleto(datos.getApPaterno() + datos.getApMaterno() + datos.getNombre());
            }else {
                datos.setNombreCompleto(datos.getApPaterno() + " " + datos.getApMaterno() + " " + datos.getNombre()); 
            }
            
            datos.setCorrNombre(stm.getLong(6));
            
        }catch(Exception e) {
            e.printStackTrace();
        }finally{
            ConnectionFactory.freeConnection(con);
        }
        return datos;
    }
    

    private List<Certificado> getListCertificado(String rutAfectado, Long corrNombre, String rutSolicitante, Integer cCosto, String login) throws Exception{
        Connection con = null;
        ResultSet rs = null;
        List<Certificado> listCertificado = new ArrayList<Certificado>();
        try {
            con = ConnectionFactory.getConnectionConsulta();
            CallableStatement stmCert = con.prepareCall("{?=CALL SQ_CertifConsLey20575_ADF(?, ?, ?, ?, ?, ?, ?, ?)}");
            stmCert.registerOutParameter(1, Types.INTEGER);

            stmCert.setString(2, rutAfectado);
            stmCert.setLong(3, corrNombre);
            stmCert.setString(4, rutSolicitante);
            stmCert.setInt(5, cCosto);
            stmCert.setString(6, login);
            stmCert.setInt(7, 0);

            stmCert.registerOutParameter(8, Types.NUMERIC);
            stmCert.registerOutParameter(9, Types.VARCHAR);


            rs = stmCert.executeQuery();
            SimpleDateFormat fmtHour = new SimpleDateFormat("HH:mm");
            while (rs.next()) {
                Certificado certificado = new Certificado();
                certificado.setFechaConsulta(rs.getTimestamp("Fld_Fecha"));
                certificado.setHoraConsulta(fmtHour.format(certificado.getFechaConsulta()));
                certificado.setRutRequirente(rs.getString("Fld_RutRequirente"));

                String nombre = rs.getString("Fld_Nombre_Nombres").trim();
                String apPaterno = rs.getString("Fld_Nombre_ApPat").trim();
                String apMaterno = rs.getString("Fld_Nombre_ApMat").trim();

                if (Util.isRutJuridico(certificado.getRutRequirente())) {
                    certificado.setNombreRequirente(apPaterno + apMaterno + nombre);
                } else {
                    certificado.setNombreRequirente(apPaterno + " " + apMaterno + " " + nombre);
                }

                certificado.setMotivo(rs.getString("Fld_GlosaMotivo"));
                certificado.setResponsable(rs.getString("Fld_GlosaResponsable"));

                listCertificado.add(certificado);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ConnectionFactory.freeConnection(con);
        }
        return listCertificado;
        
    }

    /**
     * @param rut
     * @param nombre
     * @param apPaterno
     * @param apMaterno
     * @throws Exception
     */
    @Override
    public void addPersona(String rut, String nombre, String apPaterno, String apMaterno) throws Exception {
        Connection con = null;
        
        try {
            if(rut == null || apPaterno == null) {
                return;
            }
            rut = Util.formatRUT(rut).toUpperCase();
            
            con = ConnectionFactory.getConnectionSybaseBIC();
            CallableStatement stm = con.prepareCall("{?=CALL SP_Nombre_ADF(?,?,?,?,?)}");
            stm.registerOutParameter(1, Types.INTEGER);
            
            stm.setString(2, rut);
            
            stm.setString(3, apPaterno==null?"":apPaterno.toUpperCase()); //Fld_Nombre_ApPat               
            stm.setString(4, apMaterno==null?"":apMaterno.toUpperCase()); //Fld_Nombre_ApMat             
            stm.setString(5, nombre==null?"":nombre.toUpperCase());    //Fld_Nombre_Nombres                 
            
            stm.registerOutParameter(6, Types.NUMERIC); //Fld_CorrNombre  
            
            stm.execute();
                        
        }catch(Exception e) {
            e.printStackTrace();
        }finally{
            ConnectionFactory.freeConnection(con);
        }
    }

    /**
     * @param rut
     * @return
     * @throws Exception
     */
    @Override
    public VerificaCertificado verificarCertificado(String rut) throws Exception{
        Connection con = null;
        VerificaCertificado verifica = new VerificaCertificado();
        try{
            rut = Util.formatRUT(rut).toUpperCase();
            con = ConnectionFactory.getConnectionConsulta();
            CallableStatement stm = con.prepareCall("{?=CALL SQ_VerifUltCertif_ADF(?,?,?,?)}");
            stm.registerOutParameter(1, Types.INTEGER);
            
            stm.setString(2, rut);
            
            stm.registerOutParameter(3, Types.DATE);    //Fld_Fecha
            stm.registerOutParameter(4, Types.BIT);     //Fld_FlagVigencia
            stm.registerOutParameter(5, Types.VARCHAR); //Fld_Mensaje
            
            stm.execute();
            
            Date ultFecha = stm.getDate(3);
            boolean flagVigencia = stm.getBoolean(4);
            String mensaje = stm.getString(5);

            verifica.setFechaVigencia(ultFecha);
            verifica.setVigencia(flagVigencia);
            verifica.setMensaje(mensaje);
            
        }catch(Exception e) {
            e.printStackTrace();
        }finally{
            ConnectionFactory.freeConnection(con);        
        }
        
        return verifica;
    }

    /**
     * @param rut
     * @return
     * @throws Exception
     */
    @Override
    public PersonaCertificadoEmitido consultaCertificadosEmitidos(String rut) throws Exception{
        PersonaCertificadoEmitido persona = new PersonaCertificadoEmitido();
        List<CertificadoEmitido> listCertificadoEmitido = new ArrayList<CertificadoEmitido>();
        Connection con = null;
        ResultSet rs = null;
        if(rut == null) {
            return persona;
        }
        try {
            rut = Util.formatRUT(rut);
            con = ConnectionFactory.getConnectionConsulta();
            CallableStatement stm = con.prepareCall("{?=CALL SQ_CertifEmitidos_ADF(?,?,?)}");
            stm.registerOutParameter(1, Types.INTEGER);
            
            stm.setString(2, rut);
            
            stm.registerOutParameter(3, Types.SMALLINT); //Fld_Cantidad
            stm.registerOutParameter(4, Types.VARCHAR);  //Fld_Mensaje
            
            rs = stm.executeQuery();
            while(rs.next()) {
                CertificadoEmitido certificadoEmitido = new CertificadoEmitido();
                
                certificadoEmitido.setRutSolicitante(rs.getString("Fld_RutSolicitante"));
                certificadoEmitido.setFechaEmision(rs.getTimestamp("Fld_Fecha"));
                certificadoEmitido.setCCosto(rs.getLong("Fld_CodCCosto"));
                certificadoEmitido.setGlosaCCosto(rs.getString("Fld_GlosaCCosto"));
                certificadoEmitido.setCodigoUsuario(rs.getString("Fld_CodUsuario"));
                
                listCertificadoEmitido.add(certificadoEmitido);  
            }
            
            persona.setNroEmisiones(stm.getInt(3));
            persona.setListCertificadoEmitido(listCertificadoEmitido);
            persona.setDatos(consultaPersona(rut));
            
             
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ConnectionFactory.freeConnection(con, rs);
        }

        return persona;
    }
}